/*
  Copyright 2007 Anders Båtstrand

      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.

 */

package org.dyndns.anderlin.jmplayer.model;

import javax.persistence.*;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * This could be things like:
 * <p/>
 * - Beethovens first symphony (root piece)
 * - The three sonatas in Beethovens opus 10 (root piece)
 * - One of the Diabelli variations (node piece)
 */
@Entity
@NamedQueries({
@NamedQuery(name = "piece_all", query = "select p from Piece p order by p.title"),
@NamedQuery(name = "piece_root", query = "select p from Piece p where p.parent is null order by p.title")
        })
public class Piece extends JmplayerObject {

    /**
     * The parent in the piece tree, if any
     */
    @ManyToOne(fetch = FetchType.EAGER)
    private Piece parent;

    /**
     * The different sub-parts. Movements etc. In a ordered list
     * TODO: Not EAGER
     */
    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
    private List<Piece> children;

    /**
     * The title of the piece, or part of a piece. Could be things like:
     * - Gnomenreigen
     * - Symphony nr. 1
     */
    @Basic
    @Column(nullable = false)
    private String title;

    /**
     * The artist that have composed or arranged this piece.
     * NB: This property is inherited automatically by the software if the piece has parents
     */
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Artist composer;

    /**
     * The year this piece (or compilation), or the arrangement, was published
     */
    @Temporal(TemporalType.DATE)
    @Column(nullable = true)
    private Date published;

    /**
     * The numberings of this piece.
     */
    @OneToMany(mappedBy = "piece", fetch = FetchType.EAGER)
    private Set<PieceNumber> pieceNumbers;

    /**
     * The piece category, ie Symphony, Sonata etc, if any
     */
    @ManyToOne
    private PieceCategory pieceCategory;

    /**
     * The piece this piece is an arrangemnet of, if any
     */
    @ManyToOne
    private Piece arrangementOf;

    /**
     * The tracks (recordings) of this piece
     */
    @OneToMany(mappedBy = "piece")
    private Set<Track> track;


    public Piece getParent() {
        return parent;
    }

    public void setParent(Piece parent) {
        this.parent = parent;
    }

    public List<Piece> getChildren() {
        return children;
    }

    public void setChildren(List<Piece> children) {
        this.children = children;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }


    public Artist getComposer() {
        return composer;
    }

    public void setComposer(Artist composer) {
        this.composer = composer;
    }

    public Date getPublished() {
        return published;
    }

    public void setPublished(Date published) {
        this.published = published;
    }

    public Set<PieceNumber> getPieceNumbers() {
        return pieceNumbers;
    }

    public void setPieceNumbers(Set<PieceNumber> pieceNumbers) {
        this.pieceNumbers = pieceNumbers;
    }

    public PieceCategory getPieceCategory() {
        return pieceCategory;
    }

    public void setPieceCategory(PieceCategory pieceCategory) {
        this.pieceCategory = pieceCategory;
    }

    public Piece getArrangementOf() {
        return arrangementOf;
    }

    public void setArrangementOf(Piece arrangementOf) {
        this.arrangementOf = arrangementOf;
    }

    public Set<Track> getTrack() {
        return track;
    }

    public void setTrack(Set<Track> track) {
        this.track = track;
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Piece piece = (Piece) o;

        if (pieceCategory != null ? !pieceCategory.equals(piece.pieceCategory) : piece.pieceCategory != null)
            return false;
        if (pieceNumbers != null ? !pieceNumbers.equals(piece.pieceNumbers) : piece.pieceNumbers != null) return false;
        if (published != null ? !published.equals(piece.published) : piece.published != null) return false;
        if (title != null ? !title.equals(piece.title) : piece.title != null) return false;

        return true;
    }

    public int hashCode() {
        int result;
        result = 31 * (title != null ? title.hashCode() : 0);
        result = 31 * result + (published != null ? published.hashCode() : 0);
        result = 31 * result + (pieceNumbers != null ? pieceNumbers.hashCode() : 0);
        result = 31 * result + (pieceCategory != null ? pieceCategory.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("Piece");
        sb.append("{title='").append(title).append('\'');
        sb.append(", published=").append(published);
        sb.append('}');
        return sb.toString();
    }
}
